package cn.jdemo.juc.thread;

/**
 *
 * Thread.interrupt()：
 * 总:当对处于阻塞状态的线程调用interrupt方法时（处于阻塞状态的线程是调用thread#sleep(), Object#wait(),thread#join()的线程)，
 *      会抛出InterruptException异常,并且会清除阻塞状态
 *
 * 使用场景：
 *     前置条件:线程的start方法启动一个线程后，线程开始执行run方法，run方法运行结束后线程退出,那为什么还需要结束一个线程呢？
 *     例如:在生产者/消费者模式中，消费者主体就是一个死循环，它不停的从队列中接受任务，执行任务，在停止程序时，我们需要一种”优雅”的方法以关闭该线程。
 *          在一些图形用户界面程序中，线程是用户启动的，完成一些任务，比如从远程服务器上下载一个文件，在下载过程中，用户可能会希望取消该任务。
 *          在一些场景中，比如从第三方服务器查询一个结果，我们希望在限定的时间内得到结果，如果得不到，我们会希望取消该任务。
 *          有时，我们会启动多个线程做同一件事，比如类似抢火车票，我们可能会让多个好友帮忙从多个渠道买火车票，只要有一个渠道买到了，我们会通知取消其他渠道。
 *     @see java.lang.Thread#stop() 过时，不使用
 *     Java中，停止一个线程的主要机制是中断，中断并不是强迫终止一个线程，它是一种协作机制，是给线程传递一个取消信号，但是由线程来决定如何以及何时退出；
 *
 * @see java.lang.Thread#interrupted() 静态方法 == Thread.currentThread().isInterrupted(true);
 * 该静态方法返回当前线程的中断状态，然后清除当前线程的中断状态
 *
 * @see java.lang.Thread#isInterrupted() 实例方法
 * 该实例方法返回当前线程的中断状态
 */
public class interruptDemo {
    public static void main(String[] args) throws InterruptedException {
        // test01();
        // test02();
        // test03();
        // test04();
        // test05();
        test06();
    }

    /**
     * 执行结果:
     * Thread-0:前
     * 状态2:false
     * 状态2:false
     * 状态2:false
     * ... ...
     */
    /**
     * (1)thread.interrupt() 设置中断标志
     * (2)第一个 while循环中 Thread.interrupted() 返回true，并清除中断状态
     * (3)第一个 while循环中 Thread.interrupted() 返回false，故一直执行
     */
    private static void test05() {
        Thread thread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ":前");
            // (2)
            while(!Thread.interrupted()){
                System.out.println("状态1:"+Thread.currentThread().isInterrupted());
            }
            // (3)
            while(!Thread.interrupted()){
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("状态2:"+Thread.currentThread().isInterrupted());
            }
            System.out.println(Thread.currentThread().getName() + ":后");
        });

        thread.start();
        // (1)
        thread.interrupt();
    }

    static volatile boolean isSucc = false;
    // 应用场景
    private static void test06() throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ":取票前");
            while(!Thread.interrupted()){
                System.out.println("取票中:"+Thread.currentThread().isInterrupted()+":"+isSucc);
                isSucc = true;
            }
            System.out.println(Thread.currentThread().getName() + ":取票后");
        });

        thread.start();

        Thread.sleep(1000L);
        thread.interrupt();
    }

    /*
    中断异常
    @see java.lang.Thread.interrupt() 的注释，哪些情况下会报下述错误
    interrupt()方法只是设置线程的中断标记，当对处于阻塞状态的线程调用interrupt方法时（处于阻塞状态的线程是调用sleep, wait, join的线程)，会抛出InterruptException异常，而这个异常会清除中断标记

    执行结果:
    Thread-0:前
    java.lang.InterruptedException: sleep interrupted
	    at java.lang.Thread.sleep(Native Method)
	    at com.willbj.thread.interruptDemo.lambda$test01$0(interruptDemo.java:23)
	    at java.lang.Thread.run(Thread.java:748)
    Thread-0:后
     */
    private static void test01() {
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+":前");
            Thread.currentThread().interrupt();
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":后");
        }).start();
    }

    /*
    执行结果
    java.lang.InterruptedException: sleep interrupted
	    at java.lang.Thread.sleep(Native Method)
	    at com.willbj.thread.interruptDemo.lambda$test01$0(interruptDemo.java:31)
	    at java.lang.Thread.run(Thread.java:748)
    Thread-0:前
    Thread-0:后
     */
    private static void test02() {
        Thread thread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ":前");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":后");
        });

        thread.start();
        thread.interrupt();
    }

    /*
    执行结果:
    Thread-0:前
    xxxx
    xxxx
    ... ...
     */
    private static void test03() {
        Thread thread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ":前");
            int i = 0;
            while (i < 1){
                System.out.println("xxxx");
            }
            System.out.println(Thread.currentThread().getName() + ":后");
        });

        thread.start();
        thread.interrupt();
    }

    /**
     * 执行结果
     * Thread-0:前
     * Thread-0:后
     */
    private static void test04() {
        Thread thread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ":前");
            //  thread.interrupt() 设置中断标志

            while(!Thread.interrupted()){
                System.out.println("状态1:"+Thread.currentThread().isInterrupted());
            }
            System.out.println(Thread.currentThread().getName() + ":后");
        });

        thread.start();
        thread.interrupt();
    }
}
